<!DOCTYPE HTML PUBLIC "-//ORA//DTD CD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>[Chapter 11] 11.8 Dialogs</TITLE>
<META NAME="author" CONTENT="Pat Niemeyer and Josh Peck">
<META NAME="date" CONTENT="Tue Jul 22 19:01:18 1997">
<META NAME="form" CONTENT="html">
<META NAME="metadata" CONTENT="dublincore.0.1">
<META NAME="objecttype" CONTENT="book part">
<META NAME="otheragent" CONTENT="gmat dbtohtml">
<META NAME="publisher" CONTENT="O'Reilly &amp; Associates, Inc.">
<META NAME="source" CONTENT="SGML">
<META NAME="subject" CONTENT="Java">
<META NAME="title" CONTENT="Exploring Java">
<META HTTP-EQUIV="Content-Script-Type" CONTENT="text/javascript">
</HEAD>
<body vlink="#551a8b" alink="#ff0000" text="#000000" bgcolor="#FFFFFF" link="#0000ee">

<DIV CLASS=htmlnav>
<H1><a href='index.htm'><IMG SRC="gifs/smbanner.gif"
     ALT="Exploring Java" border=0></a></H1>
<table width=515 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width=172 align=left valign=top><A HREF="ch11_07.htm"><IMG SRC="gifs/txtpreva.gif" ALT="Previous" border=0></A></td>
<td width=171 align=center valign=top><B><FONT FACE="ARIEL,HELVETICA,HELV,SANSERIF" SIZE="-1">Chapter 11<br>Using and Creating GUI Components</FONT></B></TD>
<td width=172 align=right valign=top><A HREF="ch11_09.htm"><IMG SRC="gifs/txtnexta.gif" ALT="Next" border=0></A></td>
</tr>
</table>

&nbsp;
<hr align=left width=515>
</DIV>
<DIV CLASS=sect1>
<h2 CLASS=sect1><A CLASS="TITLE" NAME="EXJ-CH-11-SECT-10">11.8 Dialogs</A></h2>

<P CLASS=para>
<A NAME="CH10.D1"></A> <A NAME="CH10.D2"></A>
 
A <tt CLASS=literal>Dialog</tt> is another standard feature of
user interfaces. In Java, a <tt CLASS=literal>Dialog</tt> is a
kind of <tt CLASS=literal>Window</tt>, which means that it's
really a container into which you put other components. A
<tt CLASS=literal>Dialog</tt> can be either
<I CLASS=emphasis>modal</I> or
<I CLASS=emphasis>nonmodal</I>. A modal dialog 
seizes the attention of the user by staying in the foreground and
grabbing all input until it is satisfied. A non-modal dialog isn't
quite so insistent; you're allowed to do other things before dealing
with the dialog. <tt CLASS=literal>Dialog</tt>
objects are useful for pop-up messages and queries or important
user-driven decisions. 

<P CLASS=para>
Most of the components we've seen so far have some special kinds of
events associated with them. A <tt CLASS=literal>Dialog</tt>
doesn't have any special events. Of course, this doesn't mean that a
dialog doesn't generate events. Since a dialog is a
<tt CLASS=literal>Window</tt>, it can generate any event that a
<tt CLASS=literal>Window</tt> can. However, there aren't any
special events, like action events or item events, to worry about.
When you're dealing with a <tt CLASS=literal>Dialog</tt>, your
primary concern will be events generated by the components that you
put into the <tt CLASS=literal>Dialog</tt>. 

<P CLASS=para>
We'll do a quick example of a
<tt CLASS=literal>Dialog</tt> window and then take a look at
<tt CLASS=literal>FileDialog</tt>, a subclass of
<tt CLASS=literal>Dialog</tt> that provides an easy-to-use file-selector
component. 
Our example will be a modal dialog that asks a simple question: 

<DIV CLASS=sect2>
<h3 CLASS=sect2><A CLASS="TITLE" NAME="EXJ-CH-11-SECT-10.1">A Simple Query Dialog</A></h3>

<DIV CLASS=screen>
<P>
<PRE>
import java.awt.*;
import java.awt.event.*;
class ModalYesNoDialog extends Dialog implements ActionListener {
    private boolean isYes = false;
    ModalYesNoDialog( Frame frame, String question ) {
        super(frame, true /* modal */);
        Label label = new Label(question);
        label.setFont( new Font("Dialog",Font.PLAIN,20) );
        add( "Center", label );
        Panel yn = new Panel();
        Button button = new Button("Yes");
        button.addActionListener( this );
        yn.add( button );
        button = new Button("No");
        button.addActionListener( this );
        yn.add( button );
        add("South", yn);
        pack();
    }
    synchronized public boolean answer() {
        return isYes;
    }
    synchronized public void actionPerformed ( ActionEvent e ) {
        isYes = e.getActionCommand().equals("Yes");
        dispose();
    }
    public static void main(String[] s) {
        Frame f = new Frame();
        f.add( "Center", new Label("I'm the application") );
        f.add( "South", new Button("Can you press me?") );
        f.pack();
        f.show();
        ModalYesNoDialog query = new ModalYesNoDialog( f, "Do you love me?");
        query.show();
        if ( query.answer() == true )
            System.out.println("She loves me...");
        else
            System.out.println("She loves me not...");
    }
}
</PRE>
</DIV>

<P CLASS=para>
The heart of this example is a class called
<tt CLASS=literal>ModalYesNoDialog</tt> that implements a simple
form with a question and two buttons. To create the
<tt CLASS=literal>Dialog</tt>, our class's constructor calls its
superclass's constructor (<tt CLASS=literal>super()</tt>), which is
<tt CLASS=literal>Dialog()</tt>. When we create the dialog, we
must supply a parent <tt CLASS=literal>Frame</tt>; we also
specify that the <tt CLASS=literal>Dialog</tt> is modal. 

<P CLASS=para>
The rest of the constructor--for that matter, the rest of the
class--doesn't have any surprises. We use a
<tt CLASS=literal>Label</tt> to display the question; we add
a pair of buttons, labeled "Yes" and "No," for the user to give his
answer. We provide an <tt CLASS=literal>answer()</tt> method so
we can ask the dialog which button the user pushed; and we provide an
<tt CLASS=literal>actionPerformed()</tt> method to receive the
button events.

<P CLASS=para>
The rest of our program is an application that uses the
<tt CLASS=literal>ModalYesNoDialog</tt>. It creates a
<tt CLASS=literal>Frame</tt>, creates the
<tt CLASS=literal>ModalYesNoDialog</tt>, displays the dialog by
calling its <tt CLASS=literal>show()</tt> method, and reads the
answer. 

<P CLASS=para>
We used an application rather than an applet to demonstrate the
<tt CLASS=literal>Dialog</tt> because dialogs are somewhat
unweildy in applets. You need to have a
<tt CLASS=literal>Frame</tt> to serve as the dialog's parent, and
most applets don't need Frames. However, there's a simple workaround.
There's no reason an applet can't use an invisible frame: just create
a <tt CLASS=literal>Frame</tt>, call its
<tt CLASS=literal>pack()</tt> method, but never call its
<tt CLASS=literal>show()</tt> method. The
<tt CLASS=literal>Frame</tt> won't be displayed, but will be able
to serve as the parent to a dialog box.

<P CLASS=para>
Now let's talk briefly about nonmodal dialogs. The most obvious 
change is in the constructor: now you call

<DIV CLASS=screen>
<P>
<PRE>
new Dialog(myFrame, false);
</PRE>
</DIV>

<P CLASS=para>
But there are a few other issues to think about. Using a nonmodal
dialog is slightly more complex because it's asynchronous: the program
doesn't wait until the user responds. Therefore, you might want to
modify the <tt CLASS=literal>answer()</tt> method so that it
calls <tt CLASS=literal>wait()</tt> to wait until the user
replies. The code would look like this:

<DIV CLASS=screen>
<P>
<PRE>
// add a new boolean for the answer() method
private boolean isAnswered = false; 
// add a wait() in the answer() method
synchronized public boolean answer() {
    while ( !isAnswered )
        try { wait(); } catch (InterruptedException e) { /* error */ }
    return isYes;
}
</PRE>
</DIV>

<P CLASS=para>
If you do this, you also need to modify
<tt CLASS=literal>actionPerformed()</tt> to call
<tt CLASS=literal>notifyAll()</tt> and terminate the
<tt CLASS=literal>wait()</tt>: 

<DIV CLASS=screen>
<P>
<PRE>
    // add a notify() in the actionPeformed() method
    synchronized public void actionPerformed ( ActionEvent e ) {
        isYes = e.getActionCommand().equals("Yes");
        isAnswered = true;
        notifyAll();
        dispose();
    }
}
</PRE>
</DIV>

</DIV>

<DIV CLASS=sect2>
<h3 CLASS=sect2><A CLASS="TITLE" NAME="EXJ-CH-11-SECT-10.2">File Selection Dialog</A></h3>

<P CLASS=para>
<A NAME="CH10.FD1"></A><A NAME="CH10.FD2"></A> <A NAME="CH10.FD3"></A>
A <tt CLASS=literal>FileDialog</tt> is a standard file-selection box. As
with other AWT components, most of
<tt CLASS=literal>FileDialog</tt> is implemented in the native part of the
AWT toolkit, so it looks and acts like a standard
file selector on your platform.

<P CLASS=para>
<A NAME="CH10.ED"></A> 
Now selecting files all day can be pretty boring without a
greater purpose, so we'll exercise the
<tt CLASS=literal>FileDialog</tt> in a mini-editor
application. <tt CLASS=literal>Editor</tt> provides a text area in which
we can load and work with files. We'll stop just shy of the
capability to save and let you fill in the blanks (with a few
caveats). The <tt CLASS=literal>FileDialog</tt> created by
<tt CLASS=literal>Editor</tt> is shown in
<A HREF="ch11_05.htm#EXJ-CH-11-FIG-6">Figure 11.6</A>. 

<DIV CLASS=figure>
<h4 CLASS=figure><A CLASS="TITLE" NAME="EXJ-CH-11-FIG-9">Figure 11.9: A FileDialog</A></h4>


<p>
<img align=middle src="./figs/je1109.gif" alt="[Graphic: Figure 11-9]" width=502 height=373 border=0>

</DIV>

<DIV CLASS=screen>
<P>
<PRE>
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class Editor extends Frame implements ActionListener {
    TextArea textArea = new TextArea();
    Editor() {
        super("Editor");
        setLayout( new BorderLayout() );
        add("Center", textArea);
        Menu menu = new Menu ("File");
        menu.add ( makeMenuItem ("Load") );
        menu.add ( makeMenuItem ("Save") );
        menu.add ( makeMenuItem ("Quit") );
        MenuBar menuBar = new MenuBar();
        menuBar.add ( menu );
        setMenuBar( menuBar );
        pack();
    }
    public void actionPerformed( ActionEvent e ) {
        String command = e.getActionCommand();
        if ( command.equals("Quit") )
            dispose();
        else if ( command.equals("Load") )
            loadFile();
        else if ( command.equals("Save") )
            saveFile();
    }
    private void loadFile () {
        FileDialog fd = new FileDialog( this, "Load File", FileDialog.LOAD );
        fd.show();
        String file = fd.getFile();
        if ( file == null ) // Cancel
            return;
        try {
            FileInputStream fis = new FileInputStream ( fd.getFile() );
            byte [] data = new byte [ fis.available() ];
            fis.read( data );
            textArea.setText( new String( data ) );
        } catch ( IOException e ) { 
            textArea.setText( "Could not load file..." );
        }
    }
    private void saveFile() {
        FileDialog fd = new FileDialog( this, "Save File", FileDialog.SAVE );
        fd.show();
        // Save file data...
    }
    private MenuItem makeMenuItem( String name ) {
        MenuItem m = new MenuItem( name );
        m.addActionListener( this );
        return m;
    }
    public static void main(String[] s) {
        new Editor().show();
    }
}
</PRE>
</DIV>

<P CLASS=para>
<tt CLASS=literal>Editor</tt> is a
<tt CLASS=literal>Frame</tt> that lays 
itself out with a <tt CLASS=literal>TextArea</tt> and a pull-down
menu. From the pull-down <b>File</b> menu, we
can opt to <b>Load</b>,
<b>Save</b>, or <b>Quit</b>. The 
<tt CLASS=literal>action()</tt> method catches the events associated with
these menu selections and takes the appropriate action.

<P CLASS=para>
The interesting parts of <tt CLASS=literal>Editor</tt> are the
<tt CLASS=literal>private</tt> methods
<tt CLASS=literal>loadFile()</tt> and 
<tt CLASS=literal>saveFile()</tt>.
<tt CLASS=literal>loadFile()</tt> creates 
a new <tt CLASS=literal>FileDialog</tt> with three parameters: a parent
frame (just as in the previous <tt CLASS=literal>Dialog</tt>
example), a title, and a directive. This parameter should be
one of the <tt CLASS=literal>FileDialog</tt> class's
<tt CLASS=literal>static</tt> identifiers
<tt CLASS=literal>LOAD</tt> or <tt CLASS=literal>SAVE</tt>,
which tell the dialog 
whether to load or save a file.

<P CLASS=para>
A <tt CLASS=literal>FileDialog</tt> does its work when the
<tt CLASS=literal>show()</tt> method is called. Unlike most components,
its <tt CLASS=literal>show()</tt> method blocks the caller until it
completes its job; the file selector then disappears. After that, we
can retrieve the designated filename with the
<tt CLASS=literal>FileDialog</tt>'s <tt CLASS=literal>getFile()</tt>
method.
In <tt CLASS=literal>loadFile()</tt>, we use a fragment of code
from <A HREF="ch08_01.htm">Chapter 8, <i>Input/Output Facilities</i></A> to get the
contents of the named file. We then add 
the contents to the <tt CLASS=literal>TextArea</tt> with
<tt CLASS=literal>setText()</tt>. You can use
<tt CLASS=literal>loadFile()</tt> as a roadmap for the unfinished
<tt CLASS=literal>saveFile()</tt> method, but it would be prudent to add
the standard safety precautions. For example, you could use the
previous <tt CLASS=literal>YesNo</tt> example to prompt the user before
overwriting an existing file.

</DIV>

</DIV>


<DIV CLASS=htmlnav>

<P>
<HR align=left width=515>
<table width=515 border=0 cellpadding=0 cellspacing=0>
<tr>
<td width=172 align=left valign=top><A HREF="ch11_07.htm"><IMG SRC="gifs/txtpreva.gif" ALT="Previous" border=0></A></td>
<td width=171 align=center valign=top><a href="index.htm"><img src='gifs/txthome.gif' border=0 alt='Home'></a></td>
<td width=172 align=right valign=top><A HREF="ch11_09.htm"><IMG SRC="gifs/txtnexta.gif" ALT="Next" border=0></A></td>
</tr>
<tr>
<td width=172 align=left valign=top>ScrollPane and Scrollbars</td>
<td width=171 align=center valign=top><a href="index/idx_0.htm"><img src='gifs/index.gif' alt='Book Index' border=0></a></td>
<td width=172 align=right valign=top>Creating custom components</td>
</tr>
</table>
<hr align=left width=515>

<IMG SRC="gifs/smnavbar.gif" USEMAP="#map" BORDER=0> 
<MAP NAME="map"> 
<AREA SHAPE=RECT COORDS="0,0,108,15" HREF="../javanut/index.htm"
alt="Java in a Nutshell"> 
<AREA SHAPE=RECT COORDS="109,0,200,15" HREF="../langref/index.htm" 
alt="Java Language Reference"> 
<AREA SHAPE=RECT COORDS="203,0,290,15" HREF="../awt/index.htm" 
alt="Java AWT"> 
<AREA SHAPE=RECT COORDS="291,0,419,15" HREF="../fclass/index.htm" 
alt="Java Fundamental Classes"> 
<AREA SHAPE=RECT COORDS="421,0,514,15" HREF="../exp/index.htm" 
alt="Exploring Java"> 
</MAP>
</DIV>

</BODY>
</HTML>
